package gao.xiaolei.aop;

import gao.xiaolei.entity.GradeRule;
import gao.xiaolei.entity.TestProcess;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import gao.xiaolei.exception.GradeRuleFieldException;
import gao.xiaolei.exception.ProcessOverTimeException;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.Set;

@Aspect
@Component//不加的话识别不了表达式
public class AopVerification {

    private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Pointcut("@annotation(gao.xiaolei.annotation.ProcessTimeCheckAdd)")
    private void processAddPointCut() {

    }

    @Pointcut("@annotation(gao.xiaolei.annotation.ProcessTimeCheckAdd)")
    private void processUpdatePointCut() {
    }

    @Pointcut("@annotation(gao.xiaolei.annotation.GradeRuleCheck)")
    private void gradeRuleCheckPointCut() {
    }

    @Around("processAddPointCut()")
    private void checkProcessAddTime(ProceedingJoinPoint pjp) throws Throwable {//添加测试流程才要去检验是不是未来时间
        TestProcess testProcess = (TestProcess) pjp.getArgs()[0];
        Set<LocalDateTime> eachEndTime = new HashSet<>(3);
        int processLength = 0;
        LocalDateTime nowTime = LocalDateTime.now();
        if (testProcess.getTotalBeginTime().isBefore(nowTime) || testProcess.getTotalEndTime().isBefore(nowTime))
            throw new ProcessOverTimeException("添加测试流程的时间要是未来时间,"
                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
                    .concat(" 或 ")
                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter))
                    .concat("是过去时间！"));
        if (testProcess.getTotalBeginTime().isAfter(testProcess.getTotalEndTime()))
            throw new ProcessOverTimeException("添加测试流程的开始时间要早于结束时间,开始时间:"
                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
                    .concat("结束时间:")
                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter)));
        if (testProcess.getTrqIsInclude() == 1) {
            if (testProcess.getTrqBeginTime().isBefore(nowTime) || testProcess.getTrqEndTime().isBefore(nowTime))
                throw new ProcessOverTimeException("添加测试流程的时间要是未来时间,"
                        .concat(testProcess.getTrqBeginTime().format(dateTimeFormatter))
                        .concat(" 或 ")
                        .concat(testProcess.getTrqEndTime().format(dateTimeFormatter))
                        .concat("是过去时间！"));
            trqTimeCheck(testProcess);
            eachEndTime.add(testProcess.getTrqEndTime());
            processLength++;
        }
        if (testProcess.getDesignIsInclude() == 1) {
            if (testProcess.getDesignBeginTime().isBefore(nowTime) || testProcess.getDesignEndTime().isBefore(nowTime))
                throw new ProcessOverTimeException("添加测试流程的时间要是未来时间,"
                        .concat(testProcess.getDesignBeginTime().format(dateTimeFormatter))
                        .concat(" 或 ")
                        .concat(testProcess.getDesignEndTime().format(dateTimeFormatter))
                        .concat("是过去时间！"));
            designTimeCheck(testProcess);
            eachEndTime.add(testProcess.getDesignEndTime());
            processLength++;
        }
        if (testProcess.getRunIsInclude() == 1) {
            if (testProcess.getRunBeginTime().isBefore(nowTime) || testProcess.getRunEndTime().isBefore(nowTime))
                throw new ProcessOverTimeException("添加测试流程的时间要是未来时间,"
                        .concat(testProcess.getRunBeginTime().format(dateTimeFormatter))
                        .concat(" 或 ")
                        .concat(testProcess.getRunEndTime().format(dateTimeFormatter))
                        .concat("是过去时间！"));
            runTimeCheck(testProcess);
            eachEndTime.add(testProcess.getRunEndTime());
            processLength++;
        }
//        if (testProcess.getReportIsInclude() == 1) {
//            if (testProcess.getReportBeginTime().isBefore(nowTime) || testProcess.getReportEndTime().isBefore(nowTime))
//                throw new ProcessOverTimeException("添加测试流程的时间要是未来时间,"
//                        .concat(testProcess.getReportBeginTime().format(dateTimeFormatter))
//                        .concat(" 或 ")
//                        .concat(testProcess.getReportEndTime().format(dateTimeFormatter))
//                        .concat("是过去时间！"));
//            reportTimeCheck(testProcess);
//        }
        if (eachEndTime.size() != processLength)
            throw new ProcessOverTimeException("各阶段的时间不能相同！");
        pjp.proceed();//不使用这个函数就不会往下执行
    }

    @Around("processUpdatePointCut()")
    private void checkProcessUpdateTime(ProceedingJoinPoint pjp) throws Throwable {//如果是修改测试流程才要去检验是不是未来时间
        TestProcess testProcess = (TestProcess) pjp.getArgs()[0];
        Set<LocalDateTime> eachEndTime = new HashSet<>(3);
        int processLength = 0;
        if (testProcess.getTotalBeginTime().isAfter(testProcess.getTotalEndTime()))
            throw new ProcessOverTimeException("添加测试流程的开始时间要早于结束时间,开始时间:"
                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
                    .concat("结束时间:")
                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter)));
        if (testProcess.getTrqIsInclude() == 1) {
            trqTimeCheck(testProcess);
            eachEndTime.add(testProcess.getTrqEndTime());
            processLength++;
        }
        if (testProcess.getDesignIsInclude() == 1) {
            designTimeCheck(testProcess);
            eachEndTime.add(testProcess.getDesignEndTime());
            processLength++;
        }
        if (testProcess.getRunIsInclude() == 1) {
            runTimeCheck(testProcess);
            eachEndTime.add(testProcess.getRunEndTime());
            processLength++;
        }
//        if (testProcess.getReportIsInclude() == 1)
//            reportTimeCheck(testProcess);
        if (eachEndTime.size() != processLength)
            throw new ProcessOverTimeException("各阶段的时间不能相同！");
        pjp.proceed();//不使用这个函数就不会往下执行
    }

    @Around("gradeRuleCheckPointCut()")
    private void checkGradeRule(ProceedingJoinPoint pjp) throws Throwable {//检验评分标准的输入数据是否符合要求
        GradeRule gradeRule = (GradeRule) pjp.getArgs()[0];
        int allPercent = 0;
        if (gradeRule.getTrqIsInclude() == 1) {//如果测试需求也在评分标准内的话
            if (gradeRule.getTrqPercent() == null || gradeRule.getTrqFloors() == null)
                throw new GradeRuleFieldException("测试需求评分标准的字段不能为空！");
            allPercent = allPercent + gradeRule.getTrqPercent();
        }
        if (gradeRule.getDesignIsInclude() == 1) {//如果测试计划也在评分标准内的话
            if (gradeRule.getDesignPercent() == null || gradeRule.getDesignFloors() == null)
                throw new GradeRuleFieldException("测试计划评分标准的字段不能为空！");
            allPercent = allPercent + gradeRule.getDesignPercent();
        }
        if (gradeRule.getRunIsInclude() == 1) {//如果测试执行也在评分标准内的话
            if (gradeRule.getRunPercent() == null || gradeRule.getRunFloors() == null)
                throw new GradeRuleFieldException("测试执行评分标准的字段不能为空！");
            allPercent = allPercent + gradeRule.getRunPercent();
        }
        if (gradeRule.isBugIsInclude()) {//如果测试bug也在评分标准内的话
            if (gradeRule.getBugPercent() == null || gradeRule.getBugFloors() == null)
                throw new GradeRuleFieldException("测试BUG评分标准的字段不能为空！");
            allPercent = allPercent + gradeRule.getBugPercent();
        }
//        if (gradeRule.getReportIsInclude() == 1) {//如果测试报告也在评分标准内的话
//            if (gradeRule.getReportPercent() == null || gradeRule.getReportFloors() == null)
//                throw new GradeRuleFieldException("测试报告评分标准的字段不能为空！");
//            allPercent = allPercent + gradeRule.getReportPercent();
//        }
        if (gradeRule.getIsCheckOnWork() == 1) {//如果考勤也在评分标准内的话
            if (gradeRule.getCheckBeginDate() == null || gradeRule.getCheckEndDate() == null || gradeRule.getCheckBeginTime() == null || gradeRule.getCheckEndTime() == null || gradeRule.getCheckPercent() == null || gradeRule.getCheckMissOneDeduct() == null || gradeRule.getCheckMissDeadTime() == null)
                throw new GradeRuleFieldException("考勤评分标准的字段不能为空！");
            if (gradeRule.getCheckBeginDate().isAfter(gradeRule.getCheckEndDate()) || gradeRule.getCheckBeginTime().isAfter(gradeRule.getCheckEndTime()))
                throw new GradeRuleFieldException("考勤开始时间要早于结束时间！");
            if (gradeRule.getCheckMissDeadTime() < 1) {
                throw new GradeRuleFieldException("缺勤无成绩的字段要大于0！");
            }
            allPercent = allPercent + gradeRule.getCheckPercent();
        }
        if (gradeRule.getIsHasOtherGrade() == 1) {//如果有其他自定义评分标准的话
            if (gradeRule.getOtherGradeName() == null || gradeRule.getOtherGradePercent() == null)
                throw new GradeRuleFieldException("自定义评分标准的字段不能为空！");
            allPercent = allPercent + gradeRule.getOtherGradePercent();
        }
        if (gradeRule.getIsCalculateTeamGrade() == 1) {//如果要计算团队分数的话
            if (gradeRule.getAveragePercent() == null || gradeRule.getTrqCoverPercent() == null)
                throw new GradeRuleFieldException("团队评分标准的字段不能为空！");
            int allTeamPercent = gradeRule.getAveragePercent() + gradeRule.getTrqCoverPercent();
            if (allTeamPercent != 100)
                throw new GradeRuleFieldException("团队评分总比为".concat(String.valueOf(allTeamPercent)).concat("不等于100！"));
        }
        if (gradeRule.getIsComposeWithTeamGrade() == 1) {//如果要将团队成绩也纳入评分标准的话
            if (gradeRule.getTeamGradePercent() == null)
                throw new GradeRuleFieldException("团队评分标准的字段不能为空！");
            if (gradeRule.getIsCalculateTeamGrade() == 0)
                throw new GradeRuleFieldException("团队评分要纳入评分标准的话请先设置团队评分标准！");
        }
        if (allPercent != 100)
            throw new GradeRuleFieldException("目前评分总比为".concat(String.valueOf(allPercent)).concat("不等于100！(不包括团队评分占比)"));
        pjp.proceed();//不使用这个函数就不会往下执行
    }

    private void trqTimeCheck(TestProcess testProcess) {
        if (testProcess.getTrqBeginTime().isAfter(testProcess.getTrqEndTime()))
            throw new ProcessOverTimeException("添加测试流程的开始时间要早于结束时间,开始时间:"
                    .concat(testProcess.getTrqBeginTime().format(dateTimeFormatter))
                    .concat("结束时间:")
                    .concat(testProcess.getTrqEndTime().format(dateTimeFormatter)));
        if (testProcess.getTotalBeginTime().isAfter(testProcess.getTrqBeginTime()) || testProcess.getTotalEndTime().isBefore(testProcess.getTrqEndTime()))
            throw new ProcessOverTimeException("测试需求流程的时间块:"
                    .concat(testProcess.getTrqBeginTime().format(dateTimeFormatter))
                    .concat("~")
                    .concat(testProcess.getTrqEndTime().format(dateTimeFormatter))
                    .concat("不在总时间块:")
                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
                    .concat("~")
                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter))
                    .concat("内"));
    }

    private void designTimeCheck(TestProcess testProcess) {
        if (testProcess.getDesignBeginTime().isAfter(testProcess.getDesignEndTime()))
            throw new ProcessOverTimeException("添加测试流程的开始时间要早于结束时间,开始时间:"
                    .concat(testProcess.getDesignBeginTime().format(dateTimeFormatter))
                    .concat("结束时间:")
                    .concat(testProcess.getDesignEndTime().format(dateTimeFormatter)));
        if (testProcess.getTotalBeginTime().isAfter(testProcess.getDesignBeginTime()) || testProcess.getTotalEndTime().isBefore(testProcess.getDesignEndTime()))
            throw new ProcessOverTimeException("测试计划流程的时间块:"
                    .concat(testProcess.getDesignBeginTime().format(dateTimeFormatter))
                    .concat("~")
                    .concat(testProcess.getDesignEndTime().format(dateTimeFormatter))
                    .concat("不在总时间块:")
                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
                    .concat("~")
                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter))
                    .concat("内"));
    }

    private void runTimeCheck(TestProcess testProcess) {
        if (testProcess.getRunBeginTime().isAfter(testProcess.getRunEndTime()))
            throw new ProcessOverTimeException("添加测试流程的开始时间要早于结束时间,开始时间:"
                    .concat(testProcess.getRunBeginTime().format(dateTimeFormatter))
                    .concat("结束时间:")
                    .concat(testProcess.getRunEndTime().format(dateTimeFormatter)));
        if (testProcess.getTotalBeginTime().isAfter(testProcess.getRunBeginTime()) || testProcess.getTotalEndTime().isBefore(testProcess.getRunEndTime()))
            throw new ProcessOverTimeException("测试执行流程的时间块:"
                    .concat(testProcess.getRunBeginTime().format(dateTimeFormatter))
                    .concat("~")
                    .concat(testProcess.getRunEndTime().format(dateTimeFormatter))
                    .concat("不在总时间块:")
                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
                    .concat("~")
                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter))
                    .concat("内"));
    }

//    private void reportTimeCheck(TestProcess testProcess) {
//        if (testProcess.getReportBeginTime().isAfter(testProcess.getReportEndTime()))
//            throw new ProcessOverTimeException("添加测试流程的开始时间要早于结束时间,开始时间:"
//                    .concat(testProcess.getReportBeginTime().format(dateTimeFormatter))
//                    .concat("结束时间:")
//                    .concat(testProcess.getReportEndTime().format(dateTimeFormatter)));
//        if (testProcess.getTotalBeginTime().isAfter(testProcess.getReportBeginTime()) || testProcess.getTotalEndTime().isBefore(testProcess.getReportEndTime()))
//            throw new ProcessOverTimeException("测试报告流程的时间块:"
//                    .concat(testProcess.getReportBeginTime().format(dateTimeFormatter))
//                    .concat("~")
//                    .concat(testProcess.getReportEndTime().format(dateTimeFormatter))
//                    .concat("不在总时间块:")
//                    .concat(testProcess.getTotalBeginTime().format(dateTimeFormatter))
//                    .concat("~")
//                    .concat(testProcess.getTotalEndTime().format(dateTimeFormatter))
//                    .concat("内"));
//    }
}
